package com.dreamlike.demo.HttpUtil.Core;

import com.dreamlike.demo.HttpUtil.Annotation.Core.Request;
import com.dreamlike.demo.HttpUtil.Annotation.Param.HeaderParam;
import com.dreamlike.demo.HttpUtil.Annotation.Param.RequestBody;
import com.dreamlike.demo.HttpUtil.Enum.RequestMethod;
import com.dreamlike.demo.HttpUtil.Annotation.Param.RequestParam;
import lombok.Getter;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.http.HttpClient;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;

@Getter
public class HttpDefinition {
    public static final int DEFAULT_REQUEST_BODY_INDEX = -1;
    private String baseUri;
    private RequestMethod requestMethod;
    private String requestContentType;
    private String responseContentType;
    private boolean isAsync;
    private Integer timeoutSeconds;
    private Executor executor;
    private HttpClient.Version version;
    private Map<Integer,String> paramRecord;
    private Map<Integer,String> headersRecord;
    private Integer requestBodyIndex;

    private Method method;



    public HttpDefinition(Method method,Executor executor){
        Request request = method.getAnnotation(Request.class);

        this.baseUri = request.baseUri();
        this.requestContentType = request.requestContentType();
        this.responseContentType = request.responseContentType();
        this.isAsync = request.isAsync();
        this.requestMethod = request.method();
        this.timeoutSeconds = request.timeoutSeconds();
        this.executor = executor;
        this.paramRecord = new HashMap<>();
        this.headersRecord = new HashMap<>();
        this.requestBodyIndex = DEFAULT_REQUEST_BODY_INDEX;
        this.method = method;
        this.version = request.version();

        Parameter nowParameter;
        Parameter[] parameters = method.getParameters();
        HeaderParam nowHeaderParam;
        RequestBody nowRequestBody;
        RequestParam nowRequestParam;
        for (int i = 0; i < parameters.length; i++) {
            nowParameter = parameters[i];

            nowHeaderParam = nowParameter.getAnnotation(HeaderParam.class);
            if (nowHeaderParam != null){
                this.headersRecord.put(i, nowHeaderParam.value().isBlank()?nowParameter.getName():nowHeaderParam.value());
                continue;
            }

            nowRequestBody = nowParameter.getAnnotation(RequestBody.class);
            if (nowRequestBody != null){
                requestBodyIndex = i;
                continue;
            }

            nowRequestParam = nowParameter.getAnnotation(RequestParam.class);

            if (nowRequestParam != null && !nowRequestParam.value().isBlank()) {
                paramRecord.put(i, nowRequestParam.value());
            }else {
                paramRecord.put(i, nowParameter.getName());
            }

        }

    }
    public HttpDefinition(Method method){
        this(method,null);
    }
    public void setExecutor(Executor executor){
        this.executor = executor;
    }

    public boolean isParamKeyToValue(){
        return requestBodyIndex == DEFAULT_REQUEST_BODY_INDEX;
    }
    public String getOriginalMethodDesc(){
        return new StringBuilder()
                .append(method.getDeclaringClass())
                .append(".")
                .append(method.getName())
                .toString();
    }
}
